/*
 * Copyright (C) 2010-2011 Comcast Cable.  All Rights Reserved.
 */
package com.hercules.android.receiver.painting.resources;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.hercules.android.receiver.LogUtil;
import com.hercules.android.receiver.handlers.events.EventRaisingException;
import com.hercules.android.receiver.model.commands.XRECommand;
import com.hercules.android.receiver.model.commands.XRESetCommand;
import com.hercules.android.receiver.model.events.XREHTMLEvent;
import com.hercules.android.receiver.model.objects.XREFlash;
import com.hercules.android.receiver.model.objects.XREHTMLText;
import com.hercules.android.receiver.model.objects.XREResourceOptions;
import com.hercules.android.receiver.painting.PaintersUtil;
import com.hercules.android.receiver.painting.views.AndroidXREView;
import com.hercules.android.receiver.painting.views.FlashEmbedWebView;
import com.hercules.android.receiver.painting.views.XRELayoutParams;

/**
 * Painter for {@link XREFlash} resource. Just url of flash application is painted as plain text.
 * <p>
 * AndroidAssembly1 this class was added in Android Assembly 1
 * <p>
 * <b>Thread safety:</b> Not thread safe, because base class is not thread safe
 *
 * @author 7realm
 * @version 1.0
 */
public class XREFlashPainter extends BaseXREResourcePainter {
	/** Represents webView that will be used to display HTML content. */
    private WebView webView;
    /** Represents default font size for WebView. */
    private int defaultFontSize;
    
    /**
     * Constructor for class {@link XREFlashPainter}.
     *
     * @param xreResource the {@link XREFlash}
     */
    public XREFlashPainter(XREFlash xreResource) {
        super(xreResource);
    }

    /**
     * Performs initialize actions.
     *
     * @throws IllegalStateException if required fields are not set
     */
    @Override
    public void init() {
        final String methodName = "init";
        LogUtil.enter(getLogger(), this, methodName);

        try {
            PaintersUtil.checkState(getReceiver(), "receiver");
            PaintersUtil.checkState(getXREView(), "xreView");
            PaintersUtil.checkState(getAndroidView(), "androidView");

            // add WebView to UI view
            getAndroidView().runOnUI(new Runnable() {
                public void run() {
                    synchronized (XREFlashPainter.this) {
                        // setup the web view
                        webView = new FlashEmbedWebView(getAndroidView().getContext());

                        // get font size
                        defaultFontSize = webView.getSettings().getDefaultFontSize();
                    }

                    webView.getSettings().setPluginState(PluginState.ON);

                    webView.setBackgroundColor(1000);
                    webView.setClipToPadding(false);
                    //webView.setClipChildren(false);
                    webView.setHorizontalScrollBarEnabled(false);
                    webView.setVerticalScrollBarEnabled(false);
                    webView.setLayoutParams(new XRELayoutParams(getXREView()));

                    // AndroidAssembly3 enable javascript
                    webView.getSettings().setJavaScriptEnabled(true);

                    // add html link click listener
                    webView.setWebViewClient(new WebViewClient() {
                        /**
                         * Invalidates parent view after loading.
                         *
                         * @param view the current view
                         * @param url the loaded url
                         */
                        @Override
                        public void onPageFinished(WebView view, String url) {
                            super.onPageFinished(view, url);

                            // invalidate parent
                            ((AndroidXREView) getAndroidView().getParent()).invalidate();
                        }
                    });

                    // add view
                    getAndroidView().addView(webView);
                    getAndroidView().setClipChildren(true);

                    // load data and invalidate
                    loadData(methodName);
                    getAndroidView().invalidate();
                }
            });

        } catch (IllegalStateException e) {
            throw LogUtil.error(getLogger(), this, methodName, e);
        }

        LogUtil.exit(getLogger(), this, methodName);
    }
    
    /**
     * Performs clean up.
     *
     * @throws IllegalStateException if required fields are not set
     */
    @Override
    public void finish() {
        String methodName = "finish";
        LogUtil.enter(getLogger(), this, methodName);

        try {
            PaintersUtil.checkState(getReceiver(), "receiver");
            synchronized (this) {
                PaintersUtil.checkState(webView, "webView");
            }

            getAndroidView().runOnUI(new Runnable() {
                public void run() {
                    // remove view
                    getAndroidView().removeView(webView);

                    // release the web view
                    webView.destroy();
                }
            });
        } catch (IllegalStateException e) {
            throw LogUtil.error(getLogger(), this, methodName, e);
        }

        LogUtil.exit(getLogger(), this, methodName);
    }
    
    /**
     * Handle {@link XRECommand}.
     *
     * @param command the command to handle
     */
    @Override
    public void handleCommand(XRECommand command) {
        final String methodName = "handleCommand";
        LogUtil.enter(getLogger(), this, methodName);

        synchronized (this) {
            if (webView != null) {
                if (command instanceof XRESetCommand) {
                    XRESetCommand setCommand = (XRESetCommand) command;

                    // apply layout if dimensions have changed
                    if (setCommand.getProps().containsKey("dimensions")) {
                        getAndroidView().runOnUI(new Runnable() {
                            public void run() {
                                webView.setLayoutParams(new XRELayoutParams(getXREView()));
                            }
                        });
                    }
                }

                // reload data and invalidate view
                getAndroidView().runOnUI(new Runnable() {
                    public void run() {
                        // reload WebView
                        loadData(methodName);

                        webView.invalidate();
                    }
                });
            }
        }
        LogUtil.exit(getLogger(), this, methodName);
    }

    /**
     * Loads data to HTML view.
     *
     * @param methodName the name of calling method
     */
    private void loadData(final String methodName) {
        XREFlash flash = getFlash();

        LogUtil.info(getLogger(), this, methodName, "Start loading flash: {0}", flash.getUrl());
        
        XREResourceOptions options = getXREView().getResourceOptions();
        
        StringBuilder html = new StringBuilder();
        html.append(
        "<!DOCTYPE HTML>" +
        "<html>" +
        "<head>" +
        "</head>" +
        "<body position='absolute' left='0px' top='0px'>" +
        "<embed src='" + flash.getUrl() + "' width='200px' height='200px' position='absolute' left='0px' top='0px'/>" +
        "</body>" +
        "</html>");

        String temp = html.toString();
        
        // load data
        webView.loadDataWithBaseURL(null, temp, "text/html", "utf-8", null);

        LogUtil.info(getLogger(), this, methodName, "End loading HTML text: {0}", temp);
    }
    
    /**
     * Gets {@link XREHTMLText}.
     *
     * @return the corresponding {@link XREHTMLText}
     */
    private XREFlash getFlash() {
        return (XREFlash) getXREResource();
    }
}
